home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / logdaemon-2 / lib / stream_pty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-03  |  3.9 KB  |  143 lines

  1. /* Author: Wietse Venema <wietse@wzv.win.tue.nl> */
  2.  
  3. #include <sys/types.h>
  4. #include <sys/stream.h>
  5. #include <errno.h>
  6. #include <stropts.h>
  7. #include <syslog.h>
  8. #include <termio.h>
  9. #include <termios.h>
  10. #include "tiocpkt.h"
  11.  
  12. /* pty_pkt_read - convert SYSV pty packets to BSD pty packets */
  13.  
  14. int     pty_pkt_read(fd, buf, len)
  15. int     fd;
  16. char   *buf;
  17. int     len;
  18. {
  19.     struct strbuf ctl;
  20.     struct strbuf data;
  21.     char    cbuf[100];
  22.     char    dbuf[100];
  23.     int     flags;
  24.     int     ret;
  25.     struct iocblk iocblk;
  26.     struct termio termio;
  27.     struct termios termios;
  28.     static int old_flow = -1;
  29.     int     new_flow;
  30.  
  31.     /*
  32.      * Convert SYSV pckt-style messages (M_XXX) to BSD pty-style packets
  33.      * (TIOCPKT_XXX). References: SunOS 5.1 Streams Programmer's Guide,
  34.      * chapter 12; the 386BSD0.1 pty(4) manual page. The types of output we
  35.      * produce: TIOCPKT_DATA, TIOCPKT_START, TIOCPKT_STOP, TIOCKPT_FLUSHREAD,
  36.      * TIOCPKT_FLUSHWRITE, TIOCPKT_DOSTOP, TIOCPKT_NOSTOP.
  37.      * 
  38.      * Rather than imposing alignment constraints on the input buffer, we make
  39.      * copies of ioctl control structures. The loss of performance should be
  40.      * negligible. Most of the time we will be dealing with non-control
  41.      * messages anyway.
  42.      * 
  43.      * Requests for one-byte reads (i.e. for non-data messages) are assumed to
  44.      * be requests for priority messages. This is the best we can do, given
  45.      * the semantical differences between select() and poll(). There really
  46.      * is no way to read non-data messages only.
  47.      * 
  48.      * If no output is produced, set errno to EAGAIN and try again later.
  49.      */
  50.  
  51.     if (len == 1) {
  52.     flags = RS_HIPRI;
  53.     data.maxlen = sizeof(dbuf);
  54.     data.buf = dbuf;
  55.     } else {
  56.     flags = 0;
  57.     data.maxlen = len - 1;
  58.     data.buf = buf + 1;
  59.     }
  60.     ctl.maxlen = sizeof(cbuf);
  61.     ctl.buf = cbuf;
  62.  
  63.     if (ret = getmsg(fd, &ctl, &data, &flags) < 0)
  64.     return (ret);
  65.     switch (ctl.len) {
  66.     default:
  67.     syslog(LOG_ERR, "bad pckt control message length %d", ctl.len);
  68.     break;
  69.     case -1:                    /* more data */
  70.     case 0:
  71.     buf[0] = TIOCPKT_DATA;
  72.     return (data.len + 1);
  73.     case 1:
  74.     switch (ctl.buf[0] & 0377) {
  75.     case M_DATA:                /* regular data message */
  76.         buf[0] = TIOCPKT_DATA;
  77.         return (data.len > 0 ? data.len + 1 : 0);
  78.     case M_FLUSH:                /* flush (some) queues */
  79.         switch (data.buf[0] & FLUSHRW) {
  80.         case FLUSHW:            /* output only */
  81.         buf[0] = TIOCPKT_FLUSHWRITE;
  82.         return (1);
  83.         case FLUSHR:            /* input only */
  84.         buf[0] = TIOCPKT_FLUSHREAD;
  85.         return (1);
  86.         case FLUSHRW:            /* output and input */
  87.         buf[0] = TIOCPKT_FLUSHWRITE | TIOCPKT_FLUSHREAD;
  88.         return (1);
  89.         default:                /* ?!none?! */
  90.         break;
  91.         }
  92.         break;
  93.     case M_STOP:                /* suspend output */
  94.         buf[0] = TIOCPKT_STOP;
  95.         return (1);
  96.     case M_START:                /* resume output */
  97.         buf[0] = TIOCPKT_START;
  98.         return (1);
  99.     case M_STOPI:                /* suspend input */
  100.     case M_STARTI:                /* resume input */
  101.         /* no equivalent yet */
  102.         break;
  103.     case M_IOCTL:                /* check flow control status */
  104.         memcpy(&iocblk, data.buf, sizeof(iocblk));
  105.         switch (iocblk.ioc_cmd) {
  106.         case TCSETS:
  107.         case TCSETSW:
  108.         case TCSETSF:
  109.         memcpy(&termios, data.buf + sizeof(iocblk), sizeof(termios));
  110.         new_flow = (termios.c_cc[VSTOP] == 21
  111.                 && termios.c_cc[VSTART] == 23
  112.                 && (termios.c_iflag & IXON));
  113.         if (old_flow != new_flow) {
  114.             old_flow = new_flow;
  115.             buf[0] = (new_flow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP);
  116.             return (1);
  117.         }
  118.         break;
  119.         case TCSETA:
  120.         case TCSETAW:
  121.         case TCSETAF:
  122.         memcpy(&termio, data.buf + sizeof(iocblk), sizeof(termio));
  123.         new_flow = (termio.c_cc[VSTOP] == 21
  124.                 && termio.c_cc[VSTART] == 23
  125.                 && (termio.c_iflag & IXON));
  126.         if (old_flow != new_flow) {
  127.             old_flow = new_flow;
  128.             buf[0] = (new_flow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP);
  129.             return (1);
  130.         }
  131.         break;
  132.         default:
  133.         break;
  134.         }
  135.     }
  136.     break;
  137.     }
  138.     /* No output produced - try again later. */
  139.  
  140.     errno = EAGAIN;
  141.     return (-1);
  142. }
  143.